package com.jwthhealth_pub.wristband.manager;

import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattDescriptor;
import android.bluetooth.BluetoothGattService;
import android.util.Log;

import com.jwthhealth_pub.common.DataUtil;
import com.jwthhealth_pub.wristband.service.WristBandService;

import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

import static com.jwthhealth_pub.common.LogUtil.makeLogTag;

/**
 * 手环服务
 * <p>
 * ffc0 ff12 发送命令特征
 * <p>
 * Created by liuzhen on 2017/11/23.
 */

public class WristbandManager {

    public static final int BLE_INFO = 0;
    public static final int BLE_BASE_INFO_ONE = 20;
    public static final int BLE_BASE_INFO_TWO = 22;
    public static final int BRACELET_MAC_ADDRESS = 24;
    public static final int BLE_BASE_INFO_THI = 26;
    public static final int BLE_BASE_INFO_FOR = 28;
    public static final int STEP_CHARAC_ID = 56;
    public static final int MASSDATA_CHARAC_ID = 74;
    public static final int KCAL_SPORTSTATE_ID = 70;
    public static final int HEART_CHARAC_ID = 44;
    public static final int BLOOD_NOTIFY_CHARAC_ID = 50;
    public static final int BRACELET_CUR_TIME = 67;

    private static String TAG = makeLogTag(WristbandManager.class);

    private BluetoothGatt mGattService;

    public WristbandManager(BluetoothGatt gattServices) {
        this.mGattService = gattServices;
    }

    /**
     * 获取写入特征
     * ffc0 ff12
     *
     * @return target character
     */
    private BluetoothGattCharacteristic getTargetGattChar(String targetServiceId, String targetCharacterId) {
        for (BluetoothGattService gattService : mGattService.getServices()) {
            String uuid = gattService.getUuid().toString();
            String serviceId = uuid.substring(4, 8);
            if (serviceId.equals(targetServiceId)) {
                List<BluetoothGattCharacteristic> characteristics = gattService.getCharacteristics();
                for (BluetoothGattCharacteristic characteristic : characteristics) {
                    String characterUUid = characteristic.getUuid().toString();
                    String subCharacterUUid = characterUUid.substring(4, 8);
                    if (subCharacterUUid.equals(targetCharacterId)) {
                        return characteristic;
                    }
                }
            }
        }

        return null;
    }

    /**
     * 开始记步
     * 命令 0x01 0x02 0x11 0x00
     */
    public void startStep() {

        if (mGattService == null) return;

        BluetoothGattCharacteristic writeGattChar = getTargetGattChar("ffc0", "ff12");

        if (writeGattChar == null) return;

        writeGattChar.setValue(new byte[]{0x01, 0x02, 0x11, 0x00, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0});
        boolean b = mGattService.writeCharacteristic(writeGattChar);
        if (b)
            Log.d(TAG, "start step");
        else
            Log.d(TAG, "start step fail");
    }

    public void readStep() {
        if (mGattService == null) return;

        BluetoothGattCharacteristic targetGattChar = getTargetGattChar("ffc0", "ff11");

        if (targetGattChar == null) return;

        boolean b = mGattService.readCharacteristic(targetGattChar);

        if (b)
            Log.d(TAG, "read step");
        else {
            Log.d(TAG, "read fail");
            Timer timer = new Timer();//实例化Timer类
            timer.schedule(new TimerTask() {
                public void run() {
                    readStep();
                    this.cancel();
                }
            }, 1000);
        }
    }

    /**
     * 动态获取步数
     */
    public void notifyStep() {
        if (mGattService == null)
            return;

        BluetoothGattCharacteristic notifyCharac = getTargetGattChar("ffc0", "ff11");

        if (notifyCharac == null) return;

        List<BluetoothGattDescriptor> descriptors = notifyCharac.getDescriptors();
        for (BluetoothGattDescriptor descriptor : descriptors) {
            String uuid = descriptor.getUuid().toString();
            String subUuid = uuid.substring(4, 8);
            if (subUuid.equals("2902")) {
                descriptor.setValue(new byte[]{0x0001});

                boolean b = mGattService.writeDescriptor(descriptor);

                if (b)
                    Log.d(TAG, "notify descriptor step");
                else {
                    Log.d(TAG, "notify descriptor step fail");
                }

                break;
            }
        }

        boolean b = mGattService.setCharacteristicNotification(notifyCharac, true);

        if (b)
            Log.d(TAG, "notify step");
        else {
            Log.d(TAG, "notify step fail");
            Timer timer = new Timer();//实例化Timer类
            timer.schedule(new TimerTask() {
                public void run() {
                    notifyStep();
                    this.cancel();
                }
            }, 1000);
        }
    }

    public void clearStep() {
        if (mGattService == null) return;

        BluetoothGattCharacteristic targetGattChar = getTargetGattChar("ffc0", "ff12");

        if (targetGattChar == null) return;

        targetGattChar.setValue(new byte[]{0x01, 0x02, 0x13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0});
        boolean b = mGattService.writeCharacteristic(targetGattChar);
        if (b)
            Log.d(TAG, "clear step");
        else
            Log.d(TAG, "clear step fail");

    }

    public void stopStep() {
        if (mGattService == null) return;

        BluetoothGattCharacteristic targetGattChar = getTargetGattChar("ffc0", "ff12");

        if (targetGattChar == null) return;

        targetGattChar.setValue(new byte[]{0x01, 0x02, 0x12, 0x00, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0});
        boolean b = mGattService.writeCharacteristic(targetGattChar);
        if (b)
            Log.d(TAG, "stop step");
        else
            Log.d(TAG, "stop step fail");
    }

    /**
     * steps 4 位
     *
     * @param steps steps
     * @return step sum
     */
    public int calcStep(int[] steps) {
        int step_sum;

        int sum_part_one = 0;
        int sum_part_two = 0;
        int sum_part_thi = 0;
        int sum_part_for = 0;

        if (steps.length >= 1) {
            int step_one = steps[0];
            if (step_one >= 0 && step_one <= 128)
                sum_part_one = (int) (step_one * Math.pow(256, 3));
            else if (step_one >= -127 && step_one < 0)
                sum_part_one = (int) ((256 + step_one) * Math.pow(256, 3));
        }

        if (steps.length >= 2) {
            int step_one = steps[1];
            if (step_one >= 0 && step_one <= 128)
                sum_part_two = (int) (step_one * Math.pow(256, 2));
            else if (step_one >= -127 && step_one < 0)
                sum_part_two = (int) ((256 + step_one) * Math.pow(256, 2));
        }

        if (steps.length >= 3) {
            int step_one = steps[2];
            if (step_one >= 0 && step_one <= 128)
                sum_part_thi = (int) (step_one * Math.pow(256, 1));
            else if (step_one >= -127 && step_one < 0)
                sum_part_thi = (int) ((256 + step_one) * Math.pow(256, 1));
        }

        if (steps.length >= 4) {
            int step_one = steps[3];
            if (step_one >= 0 && step_one <= 128)
                sum_part_for = step_one;
            else if (step_one >= -127 && step_one < 0)
                sum_part_for = (256 + step_one);
        }

        step_sum = sum_part_one + sum_part_two + sum_part_thi + sum_part_for;

        return step_sum;
    }

    public static int calc(byte[] values) {

        int sum = 0;

        for (int i = 0; i < values.length; i++) {
            int unitSum = 0;
            byte value = values[i];
            if (value >= 0)
                unitSum = (int) (value * Math.pow(256, i));
            else if (value >= -127 && value < 0)
                unitSum = (int) ((256 + value) * Math.pow(256, i));

            sum += unitSum;
        }

        return sum;
    }

    /**
     * byte[] 2 int
     *
     * @param ary    byte[]
     * @param length 数组长度
     * @return int
     */
    public static int bytesToInt(byte[] ary, int length) {
        int value;

        if (length == 1) {
            value = (ary[0] & 0xFF);
        } else if (length == 2) {
            value = ((ary[0] & 0xFF)
                    | ((ary[1] << 8) & 0xFF00));
        } else {
            value = ((ary[0] & 0xFF)
                    | ((ary[1] << 8) & 0xFF00)
                    | ((ary[2] << 16) & 0xFF0000)
                    | ((ary[3] << 24) & 0xFF000000));
        }


        return value;
    }

    // TODO: 2018/1/2 此处参数应为 byte 类型
    public static int calc(int value) {

//        int res;
//
//        if (value >= -128 && value < 0) {
//            res = 256 + value;
//        } else
//            res = value;

        return value & 0xFF;
    }

    /**
     * 倒叙相加
     *
     * @param values values
     * @return sum
     */
    public static int calcRotate(byte[] values) {

        int sum = 0;

        for (int i = values.length - 1; i >= 0; i--) {
            int unitSum = 0;
            byte value = values[i];
            if (value >= 0)
                unitSum = (int) (value * Math.pow(256, i));
            else if (value >= -127 && value < 0)
                unitSum = (int) ((256 + value) * Math.pow(256, i));

            sum += unitSum;
        }

        return sum;
    }

    /**
     * 获取步数，卡路里，里程数组
     *
     * @param step 步数
     */
    public static List<String> getStepParam(int step) {

        // TODO: 2017/12/25 输入身高体重 性别
        int mGender = 0;
        int mHei = 170;
        int mWid = 60;
//        double kcal = mHei * mWid * step * 6.92 / 1000000;
        double kcal = 170 * 160 * step * 6.92 / 1000000;
        double odo;
        if (mGender == 0)
            odo = mHei * .413 * step / 100;
        else
            odo = mHei * .415 * step / 100;

        List<String> list = new ArrayList<>();
        list.add(step + "");
        list.add((int) kcal + "");

        DecimalFormat df = new DecimalFormat("######0.00");
        String formatOdo = df.format(odo / 1000);

        list.add(formatOdo);

        return list;
    }

    public void startSleep() {
        if (mGattService == null) return;

        BluetoothGattCharacteristic targetGattChar = getTargetGattChar("ffc0", "ff12");

        if (targetGattChar == null) return;

        targetGattChar.setValue(new byte[]{0x01, 0x02, 0x10, 0x00, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0});
        boolean b = mGattService.writeCharacteristic(targetGattChar);
        if (b)
            Log.d(TAG, "start sleep");
        else
            Log.d(TAG, "start sleep fail");
    }

    public void setMassDataEnable(boolean isEnable) {
        if (mGattService == null) return;

        BluetoothGattCharacteristic targetGattChar = getTargetGattChar("ffc0", "ff21");

        if (targetGattChar == null) return;

        List<BluetoothGattDescriptor> descriptors = targetGattChar.getDescriptors();
        for (BluetoothGattDescriptor descriptor : descriptors) {
            String uuid = descriptor.getUuid().toString();
            String subUuid = uuid.substring(4, 8);
            if (subUuid.equals("2902")) {
                if (isEnable)
                    descriptor.setValue(new byte[]{0x0001});
                else
                    descriptor.setValue(new byte[]{0x0000});

                boolean b = mGattService.writeDescriptor(descriptor);

                if (b)
                    Log.d(TAG, "mass data config");
                else
                    Log.d(TAG, "mass data config fail");

                break;
            }
        }

        boolean b = mGattService.setCharacteristicNotification(targetGattChar, true);
        if (b)
            Log.d(TAG, "mass data enable");
        else
            Log.d(TAG, "mass data enable fail");
    }

    private int getMassDataEnable() {
        int enableState = -1;

        if (mGattService == null) return enableState;

        BluetoothGattCharacteristic targetGattChar = getTargetGattChar("ffc0", "ff21");

        if (targetGattChar == null) return enableState;

        List<BluetoothGattDescriptor> descriptors = targetGattChar.getDescriptors();
        for (BluetoothGattDescriptor descriptor : descriptors) {
            String uuid = descriptor.getUuid().toString();
            String subUuid = uuid.substring(4, 8);
            if (subUuid.equals("2902")) {
                byte[] value = descriptor.getValue();
                if (value != null && value.length > 0)
                    enableState = value[0];
                break;
            }
        }

        return enableState;
    }

    public void readSleepTime() {
        if (mGattService == null) return;

        int massDataEnable = getMassDataEnable();
        if (massDataEnable != 1)
            setMassDataEnable(true);

        BluetoothGattCharacteristic targetGattChar = getTargetGattChar("ffc0", "ff12");

        if (targetGattChar == null) return;

        targetGattChar.setValue(new byte[]{0x01, 0x02, 0x20, 0x00, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0});
        boolean b = mGattService.writeCharacteristic(targetGattChar);

        if (b)
            Log.d(TAG, "get sleep time");
        else
            Log.d(TAG, "get sleep time fail");
    }

    public void startBlood() {
        if (mGattService == null) return;

        BluetoothGattCharacteristic writeGattChar = getTargetGattChar("ffc0", "ff12");

        if (writeGattChar == null) return;

        writeGattChar.setValue(new byte[]{0x01, 0x02, 0x02, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0});
        boolean b = mGattService.writeCharacteristic(writeGattChar);
        if (b)
            Log.d(TAG, "start blood");
        else {
            Log.d(TAG, "start blood fail");
            Timer timer = new Timer();//实例化Timer类
            timer.schedule(new TimerTask() {
                public void run() {
                    startBlood();
                    this.cancel();
                }
            }, 1000);
        }

    }

    public void stopBlood() {
        if (mGattService == null) return;

        BluetoothGattCharacteristic writeGattChar = getTargetGattChar("ffc0", "ff12");

        if (writeGattChar == null) return;

        writeGattChar.setValue(new byte[]{0x01, 0x02, 0x03, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0});
        boolean b = mGattService.writeCharacteristic(writeGattChar);
        if (b)
            Log.d(TAG, "stop blood");
        else
            Log.d(TAG, "stop blood fail");

    }

    public void notifyBlood() {
        if (mGattService == null) return;

        BluetoothGattCharacteristic targetGattChar = getTargetGattChar("1810", "2a35");

        if (targetGattChar == null) return;

        List<BluetoothGattDescriptor> descriptorList = targetGattChar.getDescriptors();
        if (descriptorList != null) {
            for (BluetoothGattDescriptor descriptor : descriptorList) {
                mGattService.writeDescriptor(descriptor);
                String uuid = descriptor.getUuid().toString();
                String subUuid = uuid.substring(4, 8);
                if (subUuid.equals("2902")) {
                    descriptor.setValue(new byte[]{0x0001});

                    boolean b = mGattService.writeDescriptor(descriptor);

                    if (b)
                        Log.d(TAG, "notify descriptor blood");
                    else {
                        Log.d(TAG, "notify descriptor blood fail");
                    }

                    break;
                }
            }
        }

        boolean b = mGattService.setCharacteristicNotification(targetGattChar, true);

        if (b)
            Log.d(TAG, "notify blood");
        else {
            Log.d(TAG, "notify blood fail");
            Timer timer = new Timer();//实例化Timer类
            timer.schedule(new TimerTask() {
                public void run() {
                    notifyBlood();
                    this.cancel();
                }
            }, 1000);
        }
    }

    public void readBlood() {
        if (mGattService == null) return;

        BluetoothGattCharacteristic targetGattChar = getTargetGattChar("1810", "2a49");

        if (targetGattChar == null) return;

        boolean b = mGattService.readCharacteristic(targetGattChar);

        if (b)
            Log.d(TAG, "read blood");
        else
            Log.d(TAG, "read blood fail");
    }

    public void readStepMassData() {
        if (mGattService == null) return;

        BluetoothGattCharacteristic targetGattChar = getTargetGattChar("ffc0", "ff13");

        if (targetGattChar == null) return;

        boolean b = mGattService.readCharacteristic(targetGattChar);

        if (b)
            Log.d(TAG, "read step mass data");
        else
            Log.d(TAG, "read step mass data fail");

    }

    public void startHeart() {
        if (mGattService == null) return;

        BluetoothGattCharacteristic writeGattChar = getTargetGattChar("ffc0", "ff12");

        if (writeGattChar == null) return;

        if (writeGattChar != null) {
            writeGattChar.setValue(new byte[]{0x01, 0x02, 0x01, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0});
            boolean b = mGattService.writeCharacteristic(writeGattChar);
            if (b)
                Log.d(TAG, "start heart");
            else
                Log.d(TAG, "start heart fail");
        }

    }

    public void stopHeart() {

        if (mGattService == null) return;

        BluetoothGattCharacteristic writeGattChar = getTargetGattChar("ffc0", "ff12");

        if (writeGattChar == null) return;

        writeGattChar.setValue(new byte[]{0x01, 0x02, 0x03, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0});
        boolean b = mGattService.writeCharacteristic(writeGattChar);
        if (b)
            Log.d(TAG, "stop heart");
        else
            Log.d(TAG, "stop heart fail");

    }

    public void readHeart() {
        if (mGattService == null) return;

        BluetoothGattCharacteristic writeGattChar = getTargetGattChar("108d", "2a38");

        if (writeGattChar == null) return;

        boolean b = mGattService.readCharacteristic(writeGattChar);

        if (b)
            Log.d(TAG, "read heart");
        else
            Log.d(TAG, "read heart fail");
    }

    public void notifyHeart() {
        if (mGattService == null) return;

        BluetoothGattCharacteristic targetGattChar = getTargetGattChar("180d", "2a37");

        if (targetGattChar == null) return;

        List<BluetoothGattDescriptor> descriptors = targetGattChar.getDescriptors();
        for (BluetoothGattDescriptor descriptor : descriptors) {
            String uuid = descriptor.getUuid().toString();
            String subUuid = uuid.substring(4, 8);
            if (subUuid.equals("2902")) {
                descriptor.setValue(new byte[]{0x0001});

                boolean b = mGattService.writeDescriptor(descriptor);

                if (b)
                    Log.d(TAG, "heart notify");
                else
                    Log.d(TAG, "heart notify fail");

                break;
            }
        }

        boolean b = mGattService.setCharacteristicNotification(targetGattChar, true);

        if (b)
            Log.d(TAG, "notify heart");
        else
            Log.d(TAG, "notify heart fail");

    }

    public void notifyKcal() {
        if (mGattService == null) return;

        BluetoothGattCharacteristic targetGattChar = getTargetGattChar("ffc0", "ff14");

        if (targetGattChar == null) return;

        List<BluetoothGattDescriptor> descriptors = targetGattChar.getDescriptors();
        for (BluetoothGattDescriptor descriptor : descriptors) {
            String uuid = descriptor.getUuid().toString();
            String subUuid = uuid.substring(4, 8);
            if (subUuid.equals("2902")) {
                descriptor.setValue(new byte[]{0x0001});

                boolean b = mGattService.writeDescriptor(descriptor);

                if (b)
                    Log.d(TAG, "kcal descriptor notify");
                else
                    Log.d(TAG, "kcal descriptor notify fail");

                break;
            }
        }

        boolean b = mGattService.setCharacteristicNotification(targetGattChar, true);

        if (b)
            Log.d(TAG, "kcal notify");
        else
            Log.d(TAG, "kcal notify fail");
    }

    /**
     * 读取疲劳度等信息
     */
    public void readSportState() {
        if (mGattService == null) return;

        BluetoothGattCharacteristic targetGattChar = getTargetGattChar("ffc0", "ff14");

        if (targetGattChar == null) return;

        boolean b = mGattService.readCharacteristic(targetGattChar);

        if (b) {
            Log.d(TAG, "read kcal");
        } else {
            Log.d(TAG, "read kcal fail");
            Timer timer = new Timer();//实例化Timer类
            timer.schedule(new TimerTask() {
                public void run() {
                    readSportState();
                    this.cancel();
                }
            }, 1000);
        }

    }

    public void writeUserInfo(int writeHei, int writeWid, int mGender) {
        if (mGattService == null) return;

        BluetoothGattCharacteristic targetGattChar = getTargetGattChar("ffc0", "ff14");

        if (targetGattChar == null) return;

//        targetGattChar.setValue(new byte[]{0, (byte)170, 60, 0, 100, 0, 1, (byte) 200, 0, 0, 0, 26, 0, 0, 0, 0, 1, (byte) 1000, 0, 0});
        if (mGender == 0) {
            //
            targetGattChar.setValue(new byte[]{0, (byte) writeHei, (byte) writeWid, 0, (byte) (writeHei * 0.413), 0, 1, (byte) 200, 0, 0, 0, 26, (byte) mGender, 0, 0, 0, 1, (byte) 1000, 0, 0});
        } else
//            targetGattChar.setValue(new byte[]{0, (byte)writeHei, (byte) writeWid, 0, (byte) (writeHei*0.415), 0, 1, (byte) 200, 0, 0, 0, 26, (byte) mGender, 0, 0, 0, 1, (byte) 1, 1, 0});
            targetGattChar.setValue(new byte[]{0, (byte) writeHei, (byte) writeWid, 0, 30, 0, 1, (byte) 200, 0, 0, 0, 26, (byte) mGender, 0, 0, 0, 1, (byte) 1, 1, 0});
        boolean b = mGattService.writeCharacteristic(targetGattChar);

        if (b)
            Log.d(TAG, "wirte kcal");
        else {
            Log.d(TAG, "write kcal fail");
            Timer timer = new Timer();//实例化Timer类
            timer.schedule(new TimerTask() {
                public void run() {
                    writeUserInfo(170, 60, 1);
                    this.cancel();
                }
            }, 1000);
        }
    }

    /**
     * 读取计步、睡眠历史数据
     */
    public void readPassStepAndSleep() {
        if (mGattService == null) return;

        BluetoothGattCharacteristic targetGattChar = getTargetGattChar("ffc0", "ff12");

        if (targetGattChar == null) return;

        //todo del
        int massDataEnable = getMassDataEnable();
        if (massDataEnable != 1)
            setMassDataEnable(true);

        targetGattChar.setValue(new byte[]{0x01, 0x02, 0x20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0});

        boolean b = mGattService.writeCharacteristic(targetGattChar);

        if (b)
            Log.d(TAG, "read step sleep");
        else {
            Log.d(TAG, "read step sleep fail");

            if (WristBandService.isConn) {
                Timer timer = new Timer();//实例化Timer类
                timer.schedule(new TimerTask() {
                    public void run() {
                        readPassStepAndSleep();
                        this.cancel();
                    }
                }, 1000);
            }
        }
    }

    public void getPassDynamicHeart() {
        if (mGattService == null) return;

        BluetoothGattCharacteristic targetGattChar = getTargetGattChar("ffc0", "ff12");

        if (targetGattChar == null) return;

        targetGattChar.setValue(new byte[]{0x01, 0x02, 0x21, 0x00, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0});

        boolean b = mGattService.writeCharacteristic(targetGattChar);

        if (b)
            Log.d(TAG, "read pass dynamic heart");
        else
            Log.d(TAG, "read pass dynamic heart fail");

    }

    public void getPassStaticHeart() {
        if (mGattService == null) return;

        BluetoothGattCharacteristic targetGattChar = getTargetGattChar("ffc0", "ff12");

        if (targetGattChar == null) return;

        int massDataEnable = getMassDataEnable();
        if (massDataEnable != 1)
            setMassDataEnable(true);

        targetGattChar.setValue(new byte[]{0x01, 0x02, 0x22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0});

        boolean b = mGattService.writeCharacteristic(targetGattChar);

        if (b)
            Log.d(TAG, "read pass static heart");
        else {
            Log.d(TAG, "read pass staic heart fail");
            Timer timer = new Timer();//实例化Timer类
            timer.schedule(new TimerTask() {
                public void run() {
                    getPassStaticHeart();
                    this.cancel();
                }
            }, 1000);
        }

    }


    //历史数据重组
    public static List<List<Byte>> dataReconstitution(List<byte[]> value) {

        List<List<Byte>> recordDatas = new ArrayList<>();

        List<Byte> dataList = new ArrayList<>();

        int count = 0;

        for (int j = 0; j < value.size(); j++) {
            byte[] bytes = value.get(j);
//        for (byte[] bytes : value) {

            for (int i = 4; i < 20; i++) {
                dataList.add(bytes[i]);
            }

            count++;

            if (count == 4) {
                //4个包为一组数据
                recordDatas.add(dataList);
                dataList = new ArrayList<>();
                count = 0;
            }
        }

        return recordDatas;
    }

    /**
     * 获取蓝牙设备信息
     *
     * @param type 0 制造商， 1 产品型号， 2 系列号(mac地址) 3 硬件版本 4 软件版本
     */
    public void getBleInfo(int type) {
        String targetCharacId;

        switch (type) {
            case 0:
                targetCharacId = "2a29";
                break;
            case 1:
                targetCharacId = "2a24";
                break;
            case 2:
                targetCharacId = "2a25";
                break;
            case 3:
                targetCharacId = "2a27";
                break;
            case 4:
                targetCharacId = "2a28";
                break;
            default:
                targetCharacId = "2a25";
                break;
        }

        if (mGattService == null) return;

        BluetoothGattCharacteristic targetGattChar = getTargetGattChar("180a", targetCharacId);

        if (targetGattChar == null) return;

//        List<BluetoothGattDescriptor> descriptors = targetGattChar.getDescriptors();
//        for (int i=0; i<descriptors.size(); i++) {
//            BluetoothGattDescriptor descriptor = descriptors.get(i);
//            String uuid = descriptor.getUuid().toString();
//            if (uuid.contains("2a35")){
//                Log.d(TAG, "descriptor.getValue():" + Arrays.toString(descriptor.getValue()));
//            }
//        }

        boolean b = mGattService.readCharacteristic(targetGattChar);

        if (b)
            Log.d(TAG, "read base info");
        else {
            Log.d(TAG, "read base info fial");
            getBleInfo(type);
        }
    }

    public void intoCamema() {
        if (mGattService == null) return;

        BluetoothGattCharacteristic targetGattChar = getTargetGattChar("ffc0", "ff12");

        if (targetGattChar == null) return;

        targetGattChar.setValue(new byte[]{0x01, 0x02, 0x30, 0x00, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0});

        boolean b = mGattService.writeCharacteristic(targetGattChar);

        if (b)
            Log.d(TAG, "into camema");
        else
            Log.d(TAG, "into camema fail");
    }

    public void outCamema() {
        if (mGattService == null) return;

        BluetoothGattCharacteristic targetGattChar = getTargetGattChar("ffc0", "ff12");

        if (targetGattChar == null) return;

        targetGattChar.setValue(new byte[]{0x01, 0x02, 0x31, 0x00, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0});

        boolean b = mGattService.writeCharacteristic(targetGattChar);

        if (b)
            Log.d(TAG, "out camema");
        else
            Log.d(TAG, "out camema fail");
    }

    public void intoDefence() {
        if (mGattService == null) return;

        BluetoothGattCharacteristic targetGattChar = getTargetGattChar("ffc0", "ff12");

        if (targetGattChar == null) return;

        targetGattChar.setValue(new byte[]{0x01, 0x02, 0x40, 0x00, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0});

        boolean b = mGattService.writeCharacteristic(targetGattChar);

        if (b)
            Log.d(TAG, "into defence");
        else
            Log.d(TAG, "into defence fail");
    }

    public void outDefence() {
        if (mGattService == null) return;

        BluetoothGattCharacteristic targetGattChar = getTargetGattChar("ffc0", "ff12");

        if (targetGattChar == null) return;

        targetGattChar.setValue(new byte[]{0x01, 0x02, 0x41, 0x00, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0});

        boolean b = mGattService.writeCharacteristic(targetGattChar);

        if (b)
            Log.d(TAG, "out defence");
        else
            Log.d(TAG, "out defence fail");
    }

    public void searchDev() {
        if (mGattService == null) return;

        BluetoothGattCharacteristic targetGattChar = getTargetGattChar("ffc0", "ff12");

        if (targetGattChar == null) return;

        targetGattChar.setValue(new byte[]{0x01, 0x02, 0x50, 0x02, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0});

        boolean b = mGattService.writeCharacteristic(targetGattChar);

        if (b)
            Log.d(TAG, "scan dev");
        else
            Log.d(TAG, "scan dev fail");
    }

    public void stopSearchDev() {
        if (mGattService == null) return;

        BluetoothGattCharacteristic targetGattChar = getTargetGattChar("ffc0", "ff12");

        if (targetGattChar == null) return;

        targetGattChar.setValue(new byte[]{0x01, 0x02, 0x50, 0x00, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0});

        boolean b = mGattService.writeCharacteristic(targetGattChar);

        if (b)
            Log.d(TAG, "stop scan");
        else
            Log.d(TAG, "stop scan fail");
    }

    public void appNotify() {
        if (mGattService == null) return;

        BluetoothGattCharacteristic targetGattChar = getTargetGattChar("ffc0", "ff12");

        if (targetGattChar == null) return;

        targetGattChar.setValue(new byte[]{0x03, 0x01, 0x01, Byte.parseByte("WeChat"), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0});

        boolean b = mGattService.writeCharacteristic(targetGattChar);

        if (b)
            Log.d(TAG, "app notify");
        else
            Log.d(TAG, "app notify fail");
    }

    public void phoneCall() {
        if (mGattService == null) return;

        BluetoothGattCharacteristic targetGattChar = getTargetGattChar("ffc0", "ff12");

        if (targetGattChar == null) return;

        targetGattChar.setValue(new byte[]{0x03, 0x01, 0x02, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0});

        boolean b = mGattService.writeCharacteristic(targetGattChar);

        if (b)
            Log.d(TAG, "phone call");
        else
            Log.d(TAG, "phone call fail");
    }

    public void phoneCallHandle() {
        if (mGattService == null) return;

        BluetoothGattCharacteristic targetGattChar = getTargetGattChar("ffc0", "ff12");

        if (targetGattChar == null) return;

        targetGattChar.setValue(new byte[]{0x03, 0x01, 0x03, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0});

        boolean b = mGattService.writeCharacteristic(targetGattChar);

        if (b)
            Log.d(TAG, "phone call handle");
        else
            Log.d(TAG, "phone call handle fail");
    }

    public void getThiAppMsg() {
        if (mGattService == null) return;

        BluetoothGattCharacteristic targetGattChar = getTargetGattChar("ffc0", "ff12");

        if (targetGattChar == null) return;

        targetGattChar.setValue(new byte[]{0x03, 0x02, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0});

        boolean b = mGattService.writeCharacteristic(targetGattChar);

        if (b)
            Log.d(TAG, "get Thi App Msg");
        else
            Log.d(TAG, "get Thi App Msg fail");
    }

    public void setWeather() {
        if (mGattService == null) return;

        BluetoothGattCharacteristic targetGattChar = getTargetGattChar("ffc0", "ff12");

        if (targetGattChar == null) return;

        targetGattChar.setValue(new byte[]{0x06, 0x03, 0x04, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0});

        boolean b = mGattService.writeCharacteristic(targetGattChar);

        if (b)
            Log.d(TAG, "setWeather");
        else
            Log.d(TAG, "setWeather fail");
    }

    public void startTestOne() {
        if (mGattService == null) return;

        BluetoothGattCharacteristic targetGattChar = getTargetGattChar("ffc0", "ff12");

        if (targetGattChar == null) return;

        targetGattChar.setValue(new byte[]{(byte) 0xfe, 0x01, 0x01, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0});

        boolean b = mGattService.writeCharacteristic(targetGattChar);

        if (b)
            Log.d(TAG, "start test one");
        else
            Log.d(TAG, "start test one fail");
    }

    public void startTestTwo() {
        if (mGattService == null) return;

        BluetoothGattCharacteristic targetGattChar = getTargetGattChar("ffc0", "ff12");

        if (targetGattChar == null) return;

        targetGattChar.setValue(new byte[]{(byte) 0xfe, 0x01, 0x02, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0});

        boolean b = mGattService.writeCharacteristic(targetGattChar);

        if (b)
            Log.d(TAG, "start test two");
        else
            Log.d(TAG, "start test two fail");
    }

    public void exitTest() {
        if (mGattService == null) return;

        BluetoothGattCharacteristic targetGattChar = getTargetGattChar("ffc0", "ff12");

        if (targetGattChar == null) return;

        targetGattChar.setValue(new byte[]{(byte) 0xfe, 0x01, 0x00, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0});

        boolean b = mGattService.writeCharacteristic(targetGattChar);

        if (b)
            Log.d(TAG, "exit test");
        else
            Log.d(TAG, "exit test fail");
    }

    public void setTime() {
        if (mGattService == null) return;

        BluetoothGattCharacteristic targetGattChar = getTargetGattChar("ffc0", "ff15");

        if (targetGattChar == null) return;

        try{
            String startStamp = DataUtil.Data2TimeStamp("2000-1-1 00:00:00");
            long diff = (System.currentTimeMillis() - Long.parseLong(startStamp)) / 1000;

            String hexDiff = Integer.toHexString((int) diff);

            String byte_one = hexDiff.substring(0, 2);
            String byte_two = hexDiff.substring(2, 4);
            String byte_thi = hexDiff.substring(4, 6);
            String byte_for = hexDiff.substring(6, 8);

            int int_one = Integer.parseInt(byte_one, 16);
            int int_two = Integer.parseInt(byte_two, 16);
            int int_thi = Integer.parseInt(byte_thi, 16);
            int int_for = Integer.parseInt(byte_for, 16);

//        targetGattChar.setValue(new byte[]{(byte) 0x36, (byte) 0x24, (byte) 0xbd, (byte) 0x21});
            targetGattChar.setValue(new byte[]{(byte) int_for, (byte) int_thi, (byte) int_two, (byte) int_one});


            boolean b = mGattService.writeCharacteristic(targetGattChar);

            if (b)
                Log.d(TAG, "set time");
            else {
                Log.d(TAG, "set time fail");

                Timer timer = new Timer();//实例化Timer类
                timer.schedule(new TimerTask() {
                    public void run() {
                        setTime();
                        this.cancel();
                    }
                }, 1000);

            }
        } catch (Exception e) {
            Log.e(TAG, "e:" + e);
        }
    }


    /**
     * 设置ff14返回参数为第四页
     */
    public void writeFatigue() {
        if (mGattService == null) return;

        BluetoothGattCharacteristic writeGattChar = getTargetGattChar("ffc0", "ff14");

        if (writeGattChar == null) return;

        writeGattChar.setValue(new byte[]{0x01, 0x02, 0x01, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0});
        boolean b = mGattService.writeCharacteristic(writeGattChar);
        if (b)
            Log.d(TAG, "start heart");
        else
            Log.d(TAG, "start heart fail");
    }


    public void nofifyFatigue() {
        if (mGattService == null)
            return;

        BluetoothGattCharacteristic notifyCharac = getTargetGattChar("ffc0", "ff14");

        if (notifyCharac == null) return;

        List<BluetoothGattDescriptor> descriptors = notifyCharac.getDescriptors();
        for (BluetoothGattDescriptor descriptor : descriptors) {
            String uuid = descriptor.getUuid().toString();
            String subUuid = uuid.substring(4, 8);
            if (subUuid.equals("2902")) {
                descriptor.setValue(new byte[]{0x0001});

                boolean b = mGattService.writeDescriptor(descriptor);

                if (b)
                    Log.d(TAG, "notify descriptor fatifue");
                else
                    Log.d(TAG, "notify descriptor fatifue fail");

                break;
            }
        }

        boolean b = mGattService.setCharacteristicNotification(notifyCharac, true);

        if (b)
            Log.d(TAG, "notify fatigue");
        else {
            Log.d(TAG, "notify fatigue fail");

            Timer timer = new Timer();//实例化Timer类
            timer.schedule(new TimerTask() {
                public void run() {
                    nofifyFatigue();
                    this.cancel();
                }
            }, 1000);
        }
    }
}
